home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_075 / comm / xmdmrecv.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  9KB  |  350 lines

  1. /* Comm XMODEM receive file routines */
  2. #define  XMDMRECV 1
  3. #include "globals.h"
  4. #include <fcntl.h>
  5.  
  6. #define  STARTUP     1
  7. #define  STARTBLK    2
  8. #define  BLKNUM      3
  9. #define  COMPBLK     4
  10. #define  DATA        5
  11. #define  CHKSUM      6
  12. #define  CHKSUM1     7
  13.  
  14. static int   index, state;
  15. extern void emit_tx(), emit_rx(), emits_tx(), emits_rx();
  16.  
  17. /****************************/
  18. /* xmodem recieve functions */
  19. /****************************/
  20.  
  21. XMODEM_Read_File(file)
  22. UBYTE *file;
  23. {
  24.    extern void sendchar();
  25.    extern int  readchar();
  26.  
  27.    void chop_file();
  28.    UBYTE  currsect, compsect, response;
  29.    USHORT dirty, syncerr, errors, blkerrok;
  30.    ULONG  bytes;
  31.    unsigned int i, noresponse, errsect, naks;
  32.    int ch;
  33.  
  34.    errors = errsect = naks = syncerr = noresponse = index = bytes = 0;
  35.  
  36.    blkerrok = abort = dirty = FALSE;
  37.    crcflag = xfrmode;
  38.    if ((fd = creat(file, O_CREAT | O_WRONLY)) == -1)
  39.      {
  40.        sprintf(sbuff,"\nCannot Open File %s\n",file);
  41.        emits_rx(sbuff);
  42.        send_proto(CAN); send_proto( CAN );
  43.        return FALSE;
  44.      }
  45.    else
  46.      emits_rx("\nReady to Receive File -- ESC aborts transfer\n\n");
  47.  
  48.    if(viewflg)
  49.       emit_vw(12);
  50.    Xconfig(TRUE);           /* set serial port to 8/N/1  */
  51.    sector = 1;
  52.  
  53.    if(wxflag)
  54.       if(sendWs() == TRUE)
  55.          return(WXmodem_rec(file));
  56.  
  57.    response = (crcflag) ? 'C' : NAK;
  58.    state = STARTUP;
  59.  
  60.    emits_rx("Waiting for initial handshake\n");
  61.    send_proto(response);
  62.  
  63.    while( TRUE )
  64.    {
  65.      Process_window_event();
  66.      ch = readchar(TTIME,FALSE);
  67.      if(ch == TIMEOUT)  noresponse++;
  68.      if(errors < RETRYMAX)
  69.        switch(state)
  70.        {
  71.        case STARTUP:
  72.             if(abort) return FALSE;
  73.             if( ch == TIMEOUT)
  74.             {
  75.               if(noresponse == RETRYMAX/2)
  76.               {
  77.                 crcflag = (crcflag == FALSE);
  78.                 response = crcflag ? 'C' : NAK;
  79.                 sprintf(sbuff,"\rSender not responding. Switching to %s mode\n",
  80.                 crcflag ? "CRC" : "Checksum");
  81.                 emits_rx(sbuff);
  82.               }
  83.               else if(noresponse == RETRYMAX)
  84.                       break;
  85.               send_proto(response);
  86.               continue;
  87.             }  /* fall thru to STARTBLK state */
  88.  
  89.        case STARTBLK:
  90.             if(abort) break;
  91.             switch( ch )
  92.             {
  93.               case SOH:
  94.                   emit_rx_protocol(ch);
  95.                   state = BLKNUM;
  96.                   noresponse = 0;
  97.                   response = NAK;
  98.                   if(dirty)
  99.                   {
  100.                      movmem(xbuffer,&diskbuff[index++ * SECSIZ],SECSIZ);
  101.                      dirty = FALSE;
  102.                   }
  103.                   break;
  104.               case EOT:
  105.                   if(syncerr) continue;
  106.                   emit_rx_protocol(ch);
  107.                   chop_file(index);
  108.                   close( fd );
  109.                   send_proto( ACK );
  110.                   return TRUE;
  111.               case TIMEOUT:
  112.                      send_proto( NAK );
  113.                      naks++; blkerrok = TRUE;
  114.                      errsect = sector;
  115.                      break;
  116.               default:
  117.                   syncerr = 1;
  118.                   break;
  119.             }   /* switch( ch ) */
  120.             break;
  121.  
  122.        case BLKNUM:
  123.             if(ch == TIMEOUT) break;
  124.             noresponse = 0;
  125.             emit_rx_protocol(ch);
  126.             currsect = ch;
  127.             state = COMPBLK;
  128.             if(syncerr)
  129.                if((currsect != (UBYTE)sector) && (currsect != (UBYTE)(sector - 1)))
  130.                {
  131.                   if(ch == SOH )
  132.                      state = BLKNUM;
  133.                   else
  134.                      state = STARTBLK;
  135.                }
  136.             continue;
  137.  
  138.        case COMPBLK:
  139.             if(ch == TIMEOUT) break;
  140.             emit_rx_protocol(ch);
  141.             compsect = ch;
  142.             noresponse = i = checksum = crc = 0;
  143.             state = DATA;
  144.             if(syncerr)
  145.             {
  146.                if(currsect == ~compsect)
  147.                   syncerr = 0;
  148.                else state = STARTBLK;
  149.             }
  150.             continue;
  151.  
  152.        case DATA:
  153.             if(ch == TIMEOUT) break;
  154.             noresponse = 0;
  155.             xbuffer[ i++ ] = ch;
  156.             do_crc( ch );
  157.             if(viewflg)
  158.                emit_vw( ch );
  159.             if( i == SECSIZ)
  160.                state = CHKSUM;
  161.             continue;
  162.  
  163.        case CHKSUM:
  164.             if(ch == TIMEOUT) break;
  165.             noresponse = 0;
  166.             if(crcflag)
  167.             {
  168.               state = CHKSUM1;
  169.               emit_rx_protocol(ch);
  170.               do_crc( ch );
  171.               continue;
  172.             }  /* fall thru to CHKSUM1 state */
  173.  
  174.        case CHKSUM1:
  175.             if(ch == TIMEOUT) break;
  176.             noresponse = 0;
  177.             emit_rx_protocol(ch);
  178.             state = STARTBLK;
  179.             response = NAK;
  180.             if(abort)
  181.             {
  182.                abort_xfer();
  183.                return FALSE;
  184.             }
  185.             if(!verify_checksum( ch ))
  186.             {
  187.               emits_rx("  Checksum error\n");
  188.               send_proto( NAK );
  189.               errsect = sector; naks++; errors++;
  190.               status(file,bytes,naks,errsect);
  191.               continue;
  192.             }
  193.             if(currsect != ~compsect)
  194.             {
  195.               emits_rx("  Bad block number received\n");
  196.               send_proto( NAK );
  197.               errsect = sector; naks++; errors++;
  198.               status(file,bytes,naks,errsect);
  199.               continue;
  200.             }
  201.             if(currsect == (UBYTE)(sector -1))
  202.             {
  203.                if(blkerrok)  blkerrok = FALSE;
  204.                else
  205.                {
  206.                  sprintf(sbuff,"  Duplicate block %d received\n",sector - 1);
  207.                  emits_rx(sbuff);
  208.                }
  209.                status(file,bytes,naks,errsect);
  210.                if(check_line() == FALSE)  /* if an RX char is ready */
  211.                   send_proto( ACK );        /* don't send ACK */
  212.                response = ACK;
  213.                errors++;
  214.                continue;
  215.             }
  216.             if(currsect != (UBYTE)sector )
  217.             {
  218.               emits_rx("  Sector numbering error\n");
  219.               send_proto( NAK );
  220.               errsect = sector; naks++; errors++;
  221.               status(file,bytes,naks,errsect);
  222.               continue;
  223.             }
  224.             errors = 0;
  225.             bytes += SECSIZ;
  226.             dirty = TRUE;
  227.             sprintf(sbuff,"\rReceived block %d",sector);
  228.             emits_rx(sbuff);
  229.             status(file,bytes,naks,errsect);
  230.             sector++;
  231.             if(index == numbufs)
  232.             {
  233.                if(write(fd,diskbuff,numbufs * SECSIZ) != numbufs * SECSIZ)
  234.                {
  235.                  emits_rx("\nERROR writing to file\n");
  236.                  send_proto( CAN ); send_proto( CAN );
  237.                  return FALSE;
  238.                }
  239.                index = 0;
  240.             }
  241.             if(check_line() == FALSE)  /* if an RX char is ready */
  242.                send_proto( ACK );        /* don't send ACK */
  243.             response = ACK;
  244.             continue;
  245.  
  246.      default:
  247.             sprintf(sbuff,"\nIllegal internal state %d\n",state);
  248.             emits_rx(sbuff);
  249.             state = STARTBLK;
  250.             continue;
  251.      } /* end switch */
  252.      if( noresponse == RETRYMAX || errors == RETRYMAX )
  253.      {
  254.        emits_rx("Maximum errors exceeded. XMODEM receive aborted\n");
  255.        abort_xfer();
  256.        return FALSE;
  257.      }
  258.      if(abort)
  259.      {
  260.         abort_xfer();
  261.         return FALSE;
  262.      }
  263.    } /* end while(TRUE) */
  264. }
  265.  
  266. send_proto(ch)
  267. UBYTE ch;
  268. {
  269.    sendchar(ch);
  270.    emit_tx_protocol(ch);
  271. }
  272.  
  273.  
  274. abort_xfer()
  275. {
  276.    int ch, errs = 0;
  277.  
  278.    chop_file(index);
  279.    while((ch = readchar(1,FALSE)) != TIMEOUT)
  280.       ;
  281.    while(errs++ < 3)
  282.    {
  283.       send_proto(CAN); send_proto(CAN);
  284.       if(readchar(3,FALSE) == ACK)  break;
  285.    }
  286. }
  287.  
  288. status(file,bytes,naks,errsect)
  289. UBYTE *file;
  290. ULONG bytes;
  291. USHORT naks,errsect;
  292. {
  293.     sprintf(sbuff,"File=%s  bytes=%ld   naks=%d [ %d ]\r",
  294.           file,bytes,naks,errsect);
  295.     status_line(0,sbuff);
  296. }
  297.  
  298. verify_checksum( byte )
  299. UBYTE byte;
  300. {
  301.    if(crcflag)
  302.       {
  303.          do_crc( byte );
  304.          return (int)(crc == 0);
  305.       }
  306.    else
  307.       return ( checksum == byte );
  308. }
  309.  
  310.  
  311.  
  312. /*******************************
  313.  remove pad characters from the
  314.  end of the last sector of the
  315.  file.
  316. *******************************/
  317.  
  318. void chop_file(index)
  319. {
  320.    int count,i;
  321.    UBYTE c;
  322.  
  323. /*
  324.    strip control Z  -- CP/M and Aterm 1.4 use this for PAD character.
  325.    Don't remove NULLs.  Some programs pad with NULLs.  This practice
  326.    should stop, because some icon.INFO files require a NULL as the last
  327.    character in the file to terminate an ASCII string.
  328. */
  329.   if(chopflg)
  330.    {
  331.      for(i = SECSIZ-1; i >= 0; i--)
  332.        {
  333.          c = xbuffer[ i ];
  334.          if( c == PAD )
  335.             continue;
  336.          break;
  337.        }
  338.    }
  339.   else i = SECSIZ-1;    /* not chopping, write last sector intact */
  340.  
  341.   count = 0;
  342.   if(index)
  343.      count = write(fd,diskbuff,index * SECSIZ);
  344.  
  345.   count += write(fd,xbuffer,++i);
  346.   if ( count != index * SECSIZ + i)
  347.       emits_rx("\nError writing file\n");
  348. }
  349.  
  350.